<template>
  <div class="container" :style="state.style">
    <el-alert
      v-if="state.alertShow"
      :closable="false"
      :title="`可上传文件${accept}，单次可最多选择${limit}个文件，每个文件不可大于${size}M`"
      type="info"
    />
    <el-upload
      ref="uploadRef"
      :accept="state.acceptOptions"
      :action="state.action"
      :auto-upload="autoUpload"
      :before-upload="handleBeforUpload"
      class="upload-content"
      :class="{
        uploadStyle: state.showBtnDeal,
        disUploadStyle: state.hiddenBtnDeal
      }"
      :close-on-click-modal="false"
      :data="state.formData"
      :file-list="state.fileList"
      :headers="state.headers"
      :limit="state.limit"
      list-type="picture-card"
      :multiple="true"
      :name="state.name"
      :on-change="handleChange"
      :on-error="handleError"
      :on-exceed="handleExceed"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :on-success="handleSuccess"
    >
      <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
      <el-dialog v-model="state.previewVisible" append-to-body title="查看大图">
        <div>
          <el-image :src="state.dialogImageUrl" />
        </div>
      </el-dialog>
    </el-upload>
  </div>
</template>
<script setup name="PictureUpload">
import { useMessage, useMessageBox } from "@/hooks/message";
import _ from "lodash";
import { baseURL } from "@/config";
import { queryFileList, deleteFile } from "@/api/admin/cms/file/";
import { cloneObject } from "@/utils/common";
import { getTokenValue } from "@/utils/auth";

const props = defineProps({
  fileTypeCode: {
    type: String,
    default: ""
  },
  height: {
    type: Number,
    default: 170
  },
  limit: {
    type: Number,
    default: 5
  },
  autoUpload: {
    type: Boolean,
    default: false
  },
  alertShow: {
    type: Boolean,
    default: true
  },
  storageMode: {
    type: String,
    default: "minio"
  },
  accept: {
    type: Array,
    default: function () {
      return [".jpg", ".png", ".tif", ".gif", ".jpeg"];
    }
  }
});
const emits = defineEmits(["success", "remove"]);

const uploadRef = ref(null);

const state = reactive({
  acceptOptions: props.accept.join(","),
  style: { "max-height": `${props.height}px` },
  showBtnDeal: true,
  hiddenBtnDeal: false,
  formData: {
    id: "",
    fileFlag: "0",
    objectId: "",
    type: "",
    fileTypeCode: props.fileTypeCode,
    fileTypeName: "",
    nameType: "",
    extension: "",
    fileName: "",
    fileSize: "",
    storageMode: props.storageMode,
    storageDir: ""
  },
  queryParams: {
    id: "",
    objectId: "",
    fileTypeCode: props.fileTypeCode
  },
  onChange: false,
  previewVisible: false,
  dialogImageUrl: "",
  action: `${baseURL}/admin/file/upload`,
  limit: props.limit,
  size: 2,
  name: "file",
  headers: {},
  token: "",
  fileList: [],
  picture: "picture"
});

const queryFileData = async params => {
  const res = await queryFileList(params);
  if (res.data && res.data.length > 0) {
    const fileList = [];
    res.data.forEach(item => {
      const fileExistsList = state.fileList.filter(item => {
        return item.id;
      });
      if (fileExistsList.length < 1) {
        const file = { name: "", url: "", id: "", status: "" };
        file.name = item.fileName;
        file.id = item.id;
        file.status = "success";
        file.extension = item.extension;
        file.createTime = item.createTime;
        file.storageMode = item.storageMode;
        if (file.storageMode === "db") {
          file.url = `${baseURL}/admin/file/preview?id=${item.id}`;
        } else {
          file.url = item.storageFileUrl;
        }
        fileList.push(file);
      }
    });
    if (fileList.length > 0) {
      state.fileList = fileList;
    }
    if (state.fileList.length >= state.limit) {
      state.showBtnDeal = false;
      state.hiddenBtnDeal = true;
    } else {
      state.showBtnDeal = true;
      state.hiddenBtnDeal = false;
    }
  } else {
    state.fileList = [];
  }
};

const handleChange = (file, fileList) => {
  if (file.size > 1048576 * state.size) {
    state.fileList = fileList.filter(item => {
      return item.name !== file.name;
    });
    useMessageBox().warning(`上传文件大小不能超过${props.size}MB!`);
  }
  const fileNameArray = file.name.split(".");
  const fileType = `.${fileNameArray[fileNameArray.length - 1]}`;
  if (props.accept.indexOf(fileType.toLowerCase()) === -1) {
    state.fileList = fileList.filter(item => {
      return item.uid !== file.uid;
    });
    useMessageBox().warning(`请选择合适的文件!`);
  }
  const needUploadfileList = fileList.filter(item => {
    return item.status != "success";
  });
  if (needUploadfileList && needUploadfileList.length > 0) {
    state.onChange = true;
  } else {
    state.onChange = false;
  }
  if (fileList.length >= state.limit) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
};

const handleError = (err, file) => {
  useMessageBox().warning(
    `文件[${file.raw.name}]上传失败,文件大小为${_.round(
      file.raw.size / 1024,
      0
    )}KB`
  );
};

const handleExceed = files => {
  useMessageBox().warning(`当前限制选择 ${state.limit} 个文件，本次选择了
             ${files.length}
             个文件`);
};

const handlePreview = file => {
  state.dialogImageUrl = file.url;
  state.previewVisible = true;
};

const getFileListItem = fileName => {
  const fileItem = state.fileList.filter(item => {
    return item.status === "success" && item.name === fileName;
  });
  return fileItem;
};

const handleRemove = async (file, fileList) => {
  const fileItem = getFileListItem(file.name);
  if (file && file.status === "success" && file.id) {
    await deleteFile(file.id);
  } else if (fileItem && fileItem.length > 0) {
    await deleteFile(fileItem.map(item => item.id).join(","));
  }
  const needUploadfileList = fileList.filter(item => {
    return item.status != "success";
  });
  if (needUploadfileList && needUploadfileList.length > 0) {
    state.onChange = true;
  } else {
    state.onChange = false;
  }
  if (fileList.length >= state.limit) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
  context.emit("remove", {});
};

const handleSuccess = (res, file, fileList) => {
  if (res.code === 200) {
    setTimeout(() => {
      useMessage().success(`上传完成! 共${fileList.length}个文件`, "success");
    }, 1000);
    const item = res.data;
    const fileitem = {
      name: "",
      url: "",
      id: "",
      status: "",
      extension: "",
      createTime: "",
      storageMode: "",
      uid: file.uid
    };
    fileitem.name = item.fileName;
    fileitem.id = item.id;
    fileitem.status = "success";
    fileitem.extension = item.extension;
    fileitem.createTime = item.createTime;
    fileitem.storageMode = item.storageMode;
    if (fileitem.storageMode === "db") {
      fileitem.url = `${baseURL}/admin/file/preview?id=${item.id}`;
    } else {
      fileitem.url = item.storageFileUrl;
    }
    state.fileList.push(fileitem);
    if (fileList.length >= state.limit) {
      state.showBtnDeal = false;
      state.hiddenBtnDeal = true;
    } else {
      state.showBtnDeal = true;
      state.hiddenBtnDeal = false;
    }
    context.emit("success", res.data);
  } else {
    useMessageBox().warning("上传失败");
  }
};

const handleBeforUpload = file => {
  state.formData.id = "";
  state.formData.fileName = file.name;
  state.formData.fileFlag = "0";
  state.formData.fileSize = file.size;
  state.formData.type = file.type;
};

const show = (row, readonly) => {
  if (readonly) {
    state.showBtnDeal = false;
    state.hiddenBtnDeal = true;
  } else {
    state.showBtnDeal = true;
    state.hiddenBtnDeal = false;
  }
  if (row) {
    cloneObject(state.formData, row);
    cloneObject(state.queryParams, row);
  }
  queryFileData(state.queryParams);
};

const save = async row => {
  if (row && row.objectId) {
    state.formData.objectId = row.objectId;
  }
  if (state.onChange) {
    uploadRef.value.submit();
    return true;
  } else {
    return false;
  }
};

onMounted(() => {
  const token = getTokenValue();
  state.headers["Authorization"] = `Bearer ${token}`;
  state.token = token.value;
});

defineExpose({
  close,
  save,
  show
});
</script>
<style scoped>
.upload-content .avatar {
  display: block;
  width: 190px;
  height: 190px;
}
</style>
<style lang="scss">
.uploadStyle .el-upload--picture-card {
  display: inline-block;
}

.disUploadStyle .el-upload--picture-card {
  display: none;
}

.upload-content .el-upload {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  transition: var(--el-transition-duration-fast);
}

.upload-content .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  width: 150px;
  height: 150px;
  font-size: 28px;
  color: #8c939d;
  text-align: center;
}
</style>
